<template>
    <div style="height: 100%;">
        <div style="height: 100%;display: flex;" v-if="paramsInfo.length">
            <div class="left">
                <el-scrollbar class="full-percent">
                    <div v-for="(item) in paramsInfo" class="font-auto-resize param-item-container">
                        <div :class="`param-item ${currentParam.name === item.name ? 'selected' : ''}`"
                            @click="currentParam = item">{{ item.name }}</div>
                    </div>
                </el-scrollbar>
            </div>
            <div class="right">
                <el-scrollbar class="full-percent">
                    <div v-show="currentParam.name" class="param-value">
                        <div class="param-value-title">参数类型：</div>
                        <div class="param-value-value">
                            <el-radio-group v-model="currentParam.type"
                                style="width: 400px;justify-content: space-between;">
                                <el-radio :value="1" size="large">常量</el-radio>
                                <el-radio :value="2" size="large">从SQL中取值</el-radio>
                            </el-radio-group>
                            <transition name="animate__animated " enter-active-class="animate__zoomIn animate__fast"
                                leave-active-class="animate__zoomOut animate__fast">
                                <el-row style="width: calc(100% - 400px);padding-left: 50px;"
                                    v-show="currentParam.type === 2">
                                    <el-col :span="12" style="padding-right: 10px;">
                                        <el-select v-model="dbType[currentParam.name]" placeholder="请选择数据库"
                                            @clear="clearDb" @change="clearDb" class="input-auto-resize">
                                            <el-option v-for="item in dbTypes" :key="item" :label="item"
                                                :value="item" />
                                        </el-select>
                                    </el-col>
                                    <el-col :span="12">
                                        <el-select v-model="currentParam.dbSequence" placeholder="请选择实例"
                                            class="input-auto-resize">
                                            <el-option v-for="(item, index) in dbNames" :key="index" :label="item.name"
                                                :value="item.sequence">
                                            </el-option>
                                        </el-select>
                                    </el-col>
                                </el-row>
                            </transition>
                        </div>
                        <div class="param-value-title">参数值：</div>
                        <div class="param-value-value">
                            <el-input v-model="currentParam.value" class="input-auto-resize" />
                        </div>
                        <div class="param-value-title">参数描述</div>
                        <div>
                            <el-input v-model="currentParam.desc" class="font-auto-resize" type="textarea" resize="none"
                                :rows="10" />
                        </div>
                    </div>
                </el-scrollbar>
            </div>
        </div>
        <div v-else class="no-params">
            <div>
                暂无参数
            </div>
        </div>
    </div>
</template>
<script setup>
import { useElMessage } from "@usehook"

const props = defineProps({
    type: {
        type: String,
        default: ''
    },
    sourceCode: {
        type: String,
        default: ''
    }
})

const taskParams = ["triggerTime", "currentTime", "triggerDate", "currentDate"]

//保存所有的变量名称字符串 ["xxx1","xxx2"]
let paramsInfo = $ref([])
//保存所有当前解析过的变量[{"xxx1":{},"xxx2":{}}]
let paramsContent = $ref({})
let currentParam = $ref({})
let dbLists = $ref({})
let dbTypes = $ref([])
let dbType = $ref({})
let dbNames = $computed(() => {
    return dbLists[dbType[currentParam.name]]
})

const chooseDbType = (seq) => {
    for (let key in dbLists) {
        const db = dbLists[key]
        const sequence = db.map(e => {
            return e.sequence
        })
        if (sequence.includes(seq)) {
            return key
        }
    }
    return ""
}

watch(() => currentParam, (newParam) => {
    if (newParam.dbSequence) {
        dbType[newParam.name] = chooseDbType(newParam.dbSequence)
    }
})

watch(() => paramsInfo, newVal => {
    if (!newVal.map(e => e.name).includes(currentParam.name)) currentParam = {}
})

const validate = () => {
    for (let param of paramsInfo) {
        if (param.type === 2 && !param.dbSequence) {
            currentParam = param
            useElMessage.error("变量[" + param.name + "]数据库不能为空")
            return new Promise((resolve) => {
                resolve(false)
            })
        }
        if (param.type === 2 && !param.value) {
            currentParam = param
            useElMessage.error("变量[" + param.name + "]表达式不能为空")
            return new Promise((resolve) => {
                resolve(false)
            })
        }
    }
    return new Promise((resolve) => {
        resolve(true)
    })

}

const clearDb = () => {
    currentParam.dbSequence = ""
}

const parseParams = (val) => {
    const returnValue = {}
    if (val) {
        paramsInfo = []
        if (["sql", "etl"].includes(props.type)) {
            let params = Array.from(new Set(parseParam(val)))
            //判断解析的参数是否在paramsContent中
            for (let param of params) {
                if (taskParams.includes(param)) continue
                if (Object.keys(paramsContent).includes(param)) {
                    paramsInfo.push(paramsContent[param])
                } else {
                    let newParam = { name: param, type: 1, value: "", desc: "", dbSequence: "" };
                    paramsInfo.push(newParam)
                    paramsContent[param] = newParam;
                }
                returnValue[param] = { ...paramsContent[param] }
            }
        } else if ("java" === props.type) {
            for (let param of val.match(/@TaskParam\((.*?)"[ ]*\)/g) || []) {
                let name;
                if (param.indexOf('name') === -1) {
                    name = param.match(/"(.*?)"/)
                } else {
                    name = param.match(/name[ ]*=[ ]*"(.*?)"/)
                }
                if (taskParams.includes(name[1])) continue
                if (Object.keys(paramsContent).includes(name[1])) {
                    paramsInfo.push(paramsContent[name[1]])
                } else {
                    let type = param.match(/type[ ]*=[ ]*(.*?)[,\\)]/)
                    let comment = param.match(/comment[ ]*=[ ]*"(.*?)"/)
                    let defaultValue = param.match(/defaultValue[ ]*=[ ]*"(.*?)"/)
                    let newParam = {
                        name: name && name.length > 1 ? name[1] : "",
                        type: type && type.length > 1 ? parseInt(type[1]) || 1 : 1,
                        desc: comment && comment.length > 1 ? comment[1] : "",
                        value: defaultValue && defaultValue.length > 1 ? defaultValue[1] : "",
                        dbSequence: ""
                    };
                    paramsInfo.push(newParam)
                    paramsContent[name[1]] = newParam;
                }
                returnValue[name[1]] = { ...paramsContent[name[1]] }

            }
        }

    } else {
        paramsInfo = []
    }
    currentParam = paramsInfo[0] || {}
    return returnValue
}

const checkUnexpect = (val) => {
    return val.replace(/\/\*.*?\*\//g, "").replace(/--.*/g, '').replace(/'.*?'/g, '').replace(/(\$|\#)\{.*?\}/g, '').match(/(\$|\#|\{|\}).*?/g) || val.match(/(\$|\#)\{(\}|,)/g)
}

const parseParam = (val) => {
    let allParamsMatch = val.replace(/\/\*.*?\*\//g, "").replace(/--.*/g, '').match(/(\$|\#)\{.*?}/g) || []
    let allParams = []
    for (let p of allParamsMatch) {
        let param = p.split(',')[0].replace("$", "").replace("#", "").replace("{", "").replace("}", "").replace(",", "");
        let outMode = /mode[ ]*=[ ]*(OUT|out)/g.test(p)
        if (param !== null && param !== "" && !outMode) {
            allParams.push(param)
        }
    }

    return allParams
}

const fill = (data, _db) => {
    if (data) paramsContent = data
    if (_db) {
        dbLists = _db
        dbTypes = Object.keys(dbLists)
    }
}

defineExpose({ parseParams, fill, validate })

</script>

<style scoped>
:deep(.left) {
    width: 400px;
    border-right: 1px solid rgb(227 227 227 / 50%);
    border-radius: var(--border-radius);
}

:deep(.right) {
    width: calc(100% - 400px);
    border-radius: var(--border-radius);
    padding: 5px 10px;
}

:deep(.param-item) {
    border-bottom: 1px solid var(--border-color);
    padding: 5px 10px;
}

:deep(.selected) {
    background: rgba(180, 180, 180, .5);
}

:deep(.no-params) {
    width: 100%;
    height: 80%;
    display: flex;
    align-items: center;
    justify-content: center;
}

:deep(.el-radio__label) {
    font-size: var(--font-size) !important;
    font-weight: var(--font-weight) !important;
    color: var(--font-color) !important;
}

:deep(.param-value-title) {
    font-size: calc(var(--font-size) + 5px);
    height: 50px;
    display: flex;
    align-items: center;
}

:deep(.param-value-value) {
    height: 50px;
    display: flex;
    align-items: center;
}

:deep(.el-scrollbar__bar.is-vertical) {
    width: 0;
}
</style>
